﻿using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;

using Sunyi.Project.WebPoint.BusinessLogic;
using Sunyi.Project.WebPoint.Common;
using Sunyi.Project.WebPoint.DataContract;

namespace Sunyi.Project.WebPoint.WebControl
{
    public class AttachmentListControl : System.Web.UI.WebControls.WebControl
    {
        #region Private Field

        private const string VewState_AttachmentsKey = "VS_Attachments";

        private const string DefaultUploadButtonText = "Add";
        private const string AttachmentLinkTarget = "_blank";
        private const string AttachmentPanelPrefix = "pnl_";
        private const string AttachmentHyperLinkPrefix = "link_";
        private const string AttachmentImageButtonPrefix = "ibtn_";
        private const string UploadFileControlCssStyle = "width:240px;";
        private const string UploadFileButtonCssStyle = "width:70px;";
        private const string AttachmentRemoveButtonCssStyle = "width:14px;";
        private const string AttachmentRemoveButtonImageUrl = "AttachmentRemoveButtonImage.png";

        private FileUpload fileUpload;
        private Panel pnlAttachments, pnlUpload;

        private string uploadButtonText = DefaultUploadButtonText;
        private Collection<Attachment> attachments = new Collection<Attachment>();

        #endregion

        #region Property

        protected PermissionType Mode
        {
            get
            {
                PermissionType mode = PermissionType.Read;

                WebPointPage page = this.Page as WebPointPage;

                if (page != null) mode = page.RequestPermissionType;

                return mode;
            }
        }

        public string UploadButtonText
        {
            get
            {
                return uploadButtonText;
            }
            set
            {
                uploadButtonText = value;
            }
        }

        public Collection<Attachment> Attachments
        {
            get
            {
                return attachments;
            }
        }

        #endregion

        #region Public Method

        public void LoadAttachments(Collection<Guid> attachmentIds)
        {
            if (attachmentIds == null) throw new ArgumentNullException();

            if (attachments == null) attachments = new Collection<Attachment>();
            attachments.Clear();

            AttachmentManager attachmentManager = new AttachmentManager();

            foreach (var attachmentId in attachmentIds)
            {
                Attachment attachment = attachmentManager.Select(attachmentId);
                if (attachment != null) attachments.Add(attachment);
            }

            foreach (var attachment in attachments) ConstructAttachmentControls(attachment);
        }

        #endregion

        #region Overide Method

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            pnlAttachments = new Panel();
            this.Controls.Add(pnlAttachments);

            if (this.Mode == PermissionType.Create || this.Mode == PermissionType.Update)
            {
                pnlUpload = new Panel();
                this.Controls.Add(pnlUpload);

                fileUpload = new FileUpload();
                fileUpload.Attributes.Add(WebControlCommon.ControlCssStyle, UploadFileControlCssStyle);
                pnlUpload.Controls.Add(fileUpload);

                Button btnUploadAttachment = new Button();
                btnUploadAttachment.Attributes.Add(WebControlCommon.ControlCssStyle, UploadFileButtonCssStyle);
                btnUploadAttachment.Text = string.IsNullOrEmpty(this.UploadButtonText) ? DefaultUploadButtonText : this.UploadButtonText;
                btnUploadAttachment.Click += new EventHandler(btnUploadAttachment_Click);
                pnlUpload.Controls.Add(btnUploadAttachment);
            }
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            if (ViewState[VewState_AttachmentsKey] != null)
            {
                attachments = ViewState[VewState_AttachmentsKey] as Collection<Attachment>;
                if (attachments == null) attachments = new Collection<Attachment>();

                foreach (Attachment attachment in attachments)
                {
                    ConstructAttachmentControls(attachment);
                }
            }
        }

        protected override object SaveViewState()
        {
            ViewState[VewState_AttachmentsKey] = attachments;

            return base.SaveViewState();
        }

        #endregion

        #region Private Method

        private void btnUploadAttachment_Click(object sender, EventArgs e)
        {
            if (fileUpload.HasFile)
            {
                Attachment attachment = new Attachment();
                attachment.Id = Guid.NewGuid();
                attachment.AttachmentName = attachment.Id.ToString() + Path.GetExtension(fileUpload.FileName);
                attachment.AttachmentSize = fileUpload.PostedFile.ContentLength;
                attachment.DisplayName = fileUpload.FileName;
                attachment.IsActive = true;

                WebPointPage page = this.Page as WebPointPage;
                if (page != null && page.CurrentUser != null) attachment.CreatorId = page.CurrentUser.Id;

                try
                {
                    // Save file to temp upload folder.
                    SavePostFile(attachment.AttachmentName);
                }
                catch (Exception ex)
                {
                    WebControlCommon.ShowClientMessage(this, ex.ToString());
                    return;
                }

                attachments.Add(attachment);

                ConstructAttachmentControls(attachment);
            }
        }

        private void ibtnRemove_Click(object sender, ImageClickEventArgs e)
        {
            ImageButton ibtnRemove = sender as ImageButton;
            if (ibtnRemove == null) return;

            Attachment attachment = null;
            Guid attachmentId = new Guid(ibtnRemove.CommandName);
            for (int i = 0; i < attachments.Count; i++)
            {
                if (attachments[i].Id == attachmentId)
                {
                    attachment = attachments[i];
                    break;
                }
            }

            if (attachment != null)
            {
                try
                {
                    RemoveAttachment(attachment.AttachmentName, attachment.Saved);
                }
                catch (Exception ex)
                {
                    WebControlCommon.ShowClientMessage(this, ex.ToString());
                    return;
                }
            }

            Control pnlAttachment = pnlAttachments.FindControl(AttachmentPanelPrefix + ibtnRemove.CommandName);
            if (pnlAttachment != null) pnlAttachments.Controls.Remove(pnlAttachment);

            attachments.Remove(attachment);
        }

        private void ConstructAttachmentControls(Attachment attachment)
        {
            Panel pnlAttachment = new Panel();
            pnlAttachment.ID = AttachmentPanelPrefix + attachment.Id.ToString();
            pnlAttachments.Controls.Add(pnlAttachment);

            HyperLink linkAttachment = new HyperLink();
            linkAttachment.ID = AttachmentHyperLinkPrefix + attachment.Id.ToString();
            linkAttachment.Text = attachment.DisplayName + DisplayAttachmentSize(attachment.AttachmentSize);
            linkAttachment.Target = AttachmentLinkTarget;

            if (attachment.Saved)
            {
                linkAttachment.NavigateUrl = EnvironmentSetting.UploadFolderUrl + attachment.AttachmentName;
            }
            else
            {
                linkAttachment.NavigateUrl = EnvironmentSetting.UploadTempFolderUrl + attachment.AttachmentName;
            }

            pnlAttachment.Controls.Add(linkAttachment);

            if (this.Mode == PermissionType.Create || this.Mode == PermissionType.Update)
            {
                ImageButton ibtnAttachment = new ImageButton();
                ibtnAttachment.ID = AttachmentImageButtonPrefix + attachment.Id.ToString();
                ibtnAttachment.Attributes.Add(WebControlCommon.ControlCssStyle, AttachmentRemoveButtonCssStyle);
                ibtnAttachment.ImageUrl = EnvironmentSetting.ControlImageFolderUrl + AttachmentRemoveButtonImageUrl;
                ibtnAttachment.CommandName = attachment.Id.ToString();
                ibtnAttachment.Click += new ImageClickEventHandler(ibtnRemove_Click);
                pnlAttachment.Controls.Add(ibtnAttachment);
            }
        }

        private void SavePostFile(string fileName)
        {
            if (fileUpload.HasFile)
            {
                using (FileStream fs = new FileStream(EnvironmentSetting.UploadTempFolderPath + fileName, FileMode.Create))
                {
                    fs.Write(fileUpload.FileBytes, 0, fileUpload.FileBytes.Length);
                    fs.Flush();
                }
            }
        }

        private void RemoveAttachment(string fileName, bool saved)
        {
            string attachmentPath = string.Empty;

            if (saved)
            {
                attachmentPath = EnvironmentSetting.UploadFolderPath + fileName;
            }
            else
            {
                attachmentPath = EnvironmentSetting.UploadTempFolderPath + fileName;
            }

            if (File.Exists(attachmentPath)) File.Delete(attachmentPath);
        }

        private string DisplayAttachmentSize(double attachmentSize)
        {
            const string KB = "KB";
            const string MB = "MB";
            const string Bytes = "bytes";
            const string AttachmentSizeFormatter = "F";

            string attachmentSizeInformation = string.Empty;

            if (attachmentSize <= 1024)
            {
                attachmentSizeInformation = attachmentSize.ToString() + Bytes;
            }
            else if (attachmentSize < 1024 * 1024)
            {
                attachmentSizeInformation = (attachmentSize / 1024).ToString(AttachmentSizeFormatter) + KB;
            }
            else
            {
                attachmentSizeInformation = (attachmentSize / (1024 * 1024)).ToString(AttachmentSizeFormatter) + MB;
            }

            return WebPointGlobalConstant.LeftBracket + attachmentSizeInformation + WebPointGlobalConstant.RightBracket;
        }

        #endregion
    }
}
